﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Drawing.Imaging;

namespace WpfPdfReader
{
    public class ImageHelper
    {
        public static byte[] ImageToBytes(Image image)
        {
            if (image == null)
                return null;
            using (MemoryStream ms = new MemoryStream())
            {
                using (Bitmap bitmap = new Bitmap(image))
                {
                    try
                    {
                        bitmap.Save(ms, image.RawFormat);
                    }
                    catch
                    {
                        bitmap.Save(ms, System.Drawing.Imaging.ImageFormat.Png);
                    }
                    return ms.ToArray();
                }
            }
        }

        public static Image ReadImage(byte[] bytes)
        {
            if (bytes == null)
                return null;
            //如果用using 会引起 "A generic error occurred in GDI+"
            MemoryStream memStream = new MemoryStream(bytes);
            {
                Image img = Image.FromStream(memStream);
                //img.Save(@"test2.jpg");
                return img;
            }
        }

        /// <summary>
        /// 保持纵横比
        /// </summary>
        /// <param name="srcImage"></param>
        /// <param name="newSize"></param>
        /// <returns></returns>
        public static Image GetThumbnailImage(Image srcImage, Size newSize)
        {
            if (srcImage != null && newSize != null)
            {
                int srcWidth = srcImage.Width;
                int srcHeight = srcImage.Height;
                int dstHeight = newSize.Height;
                int dstWidth = newSize.Width;
                if (srcWidth > srcHeight)
                {
                    dstHeight = newSize.Height;
                    dstWidth = Convert.ToInt32(dstHeight * (new decimal(srcWidth) / new decimal(srcHeight)));
                }
                else
                {
                    dstWidth = newSize.Width;
                    dstHeight = Convert.ToInt32(dstWidth * (new decimal(srcHeight) / new decimal(srcWidth)));
                }

                return GetImage(srcImage, new Size(dstWidth, dstHeight));
            }
            else
                return null;
        }

        /// <summary>
        /// 根据是否需要保持纵横比返回缩略图
        /// </summary>
        /// <param name="srcImage">原始图像</param>
        /// <param name="newSize">新图像大小</param>
        /// <param name="keepAspectRatio">是否保持纵横比</param>
        /// <returns></returns>
        public static Image GetThumbnailImage(Image srcImage, Size newSize, bool keepAspectRatio)
        {
            if (keepAspectRatio)
                return GetThumbnailImage(srcImage, newSize);
            else
            {
                return GetImage(srcImage, newSize);
            }
        }

        public static Icon ImageToIcon(Image image, string fileName)
        {
            Bitmap bmp = image as Bitmap;
            Icon icon = System.Drawing.Icon.FromHandle(bmp.GetHicon());
            FileStream fs = new FileStream(fileName, FileMode.OpenOrCreate);
            icon.Save(fs);
            fs.Close();
            return icon;
        }

        private static Image GetImage(Image srcImage, Size newSize)
        {
            int srcWidth = srcImage.Width;
            int srcHeight = srcImage.Height;
            int dstHeight = newSize.Height;
            int dstWidth = newSize.Width;

            Image dstImage = new Bitmap(dstWidth, dstHeight);
            Graphics g = Graphics.FromImage(dstImage);
            g.SmoothingMode = SmoothingMode.HighQuality;
            g.CompositingQuality = CompositingQuality.HighQuality;
            g.InterpolationMode = InterpolationMode.High;
            Rectangle dstRect = new Rectangle(0, 0, dstWidth, dstHeight);
            Rectangle srcRect = new Rectangle(0, 0, srcWidth, srcHeight);

            Image newImage = srcImage.Clone() as Image;
            g.DrawImage(newImage, dstRect, srcRect, GraphicsUnit.Pixel);

            using (MemoryStream ms = new MemoryStream())
            {
                try
                {
                    dstImage.Save(ms, System.Drawing.Imaging.ImageFormat.Png);
                    dstImage = Image.FromStream(ms);
                }
                catch { }
            }

            g.Dispose();

            return dstImage;
        }

        private static long totaltime;
        private static int count;
        /// <summary>
        /// 上下合并两张一样大小的图片
        /// </summary>
        /// <param name="srcImage1">图片1</param>
        /// <param name="srcImage2">图片2</param>
        /// <returns>返回合并后的图片内存流</returns>
        public static MemoryStream CombineImageVertical(System.Drawing.Image srcImage1, System.Drawing.Image srcImage2)
        {
            System.Diagnostics.Stopwatch watch = new System.Diagnostics.Stopwatch();
            watch.Start();
            count++;

            int srcWidth = srcImage1.Width;
            int srcHeight = srcImage1.Height;
            int dstHeight = srcHeight + srcImage2.Height + 5;
            int dstWidth = srcWidth;

            System.Drawing.Image dstImage = new Bitmap(dstWidth, dstHeight);
            Graphics g = Graphics.FromImage(dstImage);
            g.SmoothingMode = SmoothingMode.HighQuality;
            g.CompositingQuality = CompositingQuality.HighQuality;
            g.InterpolationMode = InterpolationMode.High;
            System.Drawing.Rectangle dstRect1 = new System.Drawing.Rectangle(0, 0, srcWidth, srcHeight);
            System.Drawing.Rectangle srcRect1 = new System.Drawing.Rectangle(0, 0, srcWidth, srcHeight);
            g.DrawImage(srcImage1, dstRect1, srcRect1, GraphicsUnit.Pixel);

            System.Drawing.Rectangle dstRect2 = new System.Drawing.Rectangle(0, srcHeight + 5, srcWidth, srcHeight);
            System.Drawing.Rectangle srcRect2 = new System.Drawing.Rectangle(0, 0, srcWidth, srcHeight);
            g.DrawImage(srcImage2, dstRect2, srcRect2, GraphicsUnit.Pixel);

            MemoryStream ms = new MemoryStream();
            dstImage.Save(ms, System.Drawing.Imaging.ImageFormat.Png);

            dstImage.Dispose();

            g.Dispose();

            watch.Stop();
            System.Diagnostics.Debug.WriteLine(watch.ElapsedMilliseconds);
            totaltime += watch.ElapsedMilliseconds;
            System.Diagnostics.Debug.WriteLine(string.Format("average time:{0}", (double)totaltime / count));

            return ms;
        }

        public static MemoryStream MergeImageVertical(System.Drawing.Image srcImage1, System.Drawing.Image srcImage2)
        {
            System.Diagnostics.Stopwatch watch = new System.Diagnostics.Stopwatch();
            watch.Start();
            count++;

            int dstHeight = srcImage1.Height + srcImage2.Height + 7;
            int dstWidth = srcImage1.Width > srcImage2.Width ? srcImage1.Width : srcImage2.Width;

            Bitmap bmp = new Bitmap(dstWidth, dstHeight, PixelFormat.Format24bppRgb);
            var imageData = bmp.LockBits(new System.Drawing.Rectangle(0, 0, dstWidth, dstHeight), ImageLockMode.ReadWrite, bmp.PixelFormat);

            Bitmap bmp1 = srcImage1 as System.Drawing.Bitmap;
            Bitmap bmp2 = srcImage2 as System.Drawing.Bitmap;
            var imageData1 = bmp1.LockBits(new System.Drawing.Rectangle(0, 0, srcImage1.Width, srcImage1.Height), ImageLockMode.ReadOnly, bmp1.PixelFormat);
            var imageData2 = bmp2.LockBits(new System.Drawing.Rectangle(0, 0, srcImage2.Width, srcImage2.Height), ImageLockMode.ReadOnly, bmp2.PixelFormat);

            int bitsPerPixel = ((int)bmp1.PixelFormat >> 8) & 0xFF;
            int bpp = bitsPerPixel / 8;

            unsafe
            {
                byte* ptrDest = (byte*)imageData.Scan0;

                byte* ptrSrc = (byte*)imageData1.Scan0;
                int height = srcImage1.Height;
                int width = srcImage1.Width;
                for (int y = 0; y < height; y++)
                {
                    byte* pl = ptrDest;
                    byte* sl = ptrSrc;
                    for (int x = 0; x < width; x++)
                    {
                        pl[0] = sl[0]; //b
                        pl[1] = sl[1]; //g
                        pl[2] = sl[2]; //r
                        pl += 3;
                        sl += 3;
                    }
                    ptrDest += imageData.Stride;
                    ptrSrc += imageData1.Stride;
                }

                bmp1.UnlockBits(imageData1);

                for (int y = 0; y < 7; y++)
                {
                    byte* pl = ptrDest;
                    for (int x = 0; x < dstWidth; x++)
                    {
                        pl[0] = (byte)126;
                        pl[1] = (byte)167;
                        pl[2] = (byte)117;
                        pl += 3;
                    }
                    ptrDest += imageData.Stride;
                }

                height = srcImage2.Height;
                width = srcImage2.Width;
                ptrSrc = (byte*)imageData2.Scan0;
                for (int y = 0; y < height; y++)
                {
                    byte* pl = ptrDest;
                    byte* sl = ptrSrc;
                    for (int x = 0; x < width; x++)
                    {
                        pl[0] = sl[0]; //b
                        pl[1] = sl[1]; //g
                        pl[2] = sl[2]; //r
                        pl += 3;
                        sl += 3;
                    }
                    ptrDest += imageData.Stride;
                    ptrSrc += imageData2.Stride;
                }

                ptrDest = (byte*)IntPtr.Zero;
                ptrSrc = (byte*)IntPtr.Zero;
                bmp2.UnlockBits(imageData2);
            }
            bmp.UnlockBits(imageData);

            imageData1 = null;
            imageData2 = null;
            imageData = null;

            MemoryStream ms = new MemoryStream();
            bmp.Save(ms, System.Drawing.Imaging.ImageFormat.Png);
            bmp.Dispose();

            System.Diagnostics.Debug.WriteLine(watch.ElapsedMilliseconds);
            totaltime += watch.ElapsedMilliseconds;
            System.Diagnostics.Debug.WriteLine(string.Format("average time:{0}", (double)totaltime / count));

            return ms;
        }
    }
}
